Skip to content

Mint for me - profile wallet selection#1925

Merged
prxt6529 merged 8 commits intomainfrom
mint-for-me-profile-wallet-selection
Feb 12, 2026
Merged

Mint for me - profile wallet selection#1925
prxt6529 merged 8 commits intomainfrom
mint-for-me-profile-wallet-selection

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Feb 11, 2026

Summary by CodeRabbit

  • New Features

    • Dual minting flows: mint for yourself or choose a Fren to mint for.
    • Recipient selector options: toggle profile card, disable single-wallet interaction, and hide Change button.
    • Mint diagnostics panel (enabled via URL) with copyable JSON diagnostics.
  • Bug Fixes

    • Ensures correct mint target when switching profiles/wallets and when switching back.
  • Tests

    • Added tests covering profile/wallet switching and mint-target behavior.
  • Chores

    • Local development impersonation support for easier dev testing.

Signed-off-by: prxt6529 <prxt@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds dev-mode wallet impersonation to connect context, extends RecipientSelector with profile/wallet rendering flags, implements dual minting flows (mint-for-fren vs mint-for-me) in ManifoldMintingConnect, adds mint diagnostics UI in ManifoldMintingWidget, and introduces tests for wallet/profile switching during mint flows.

Changes

Cohort / File(s) Summary
Tests — Manifold minting
__tests__/components/manifoldMinting/ManifoldMintingConnect.test.tsx
Adds mock for TransferModalPfp and two tests that simulate switching profiles/wallets and assert onMintFor behavior across "mint for me" and "mint for fren" flows.
Auth context — impersonation
components/auth/SeizeConnectContext.tsx
Adds dev-mode impersonation using DEV_MODE_WALLET_ADDRESS (localhost/dev); forces connection to impersonated address when present and reflects impersonation in address, isConnected, and isAuthenticated, with debounced update flow prioritized for impersonation.
Recipient selector UI
components/common/RecipientSelector.tsx
Adds props allowProfileChange, showSelectedProfileCard, disableSingleWalletSelection; conditionally renders profile card and Change button; supports non-interactive single-wallet display and propagates flags.
Manifold minting — connect UI/logic
components/manifoldMinting/ManifoldMintingConnect.tsx
Implements dual flows (Mint For Fren vs Mint For Me) with separate Fren state, derived connected recipient, reset logic on switches/account changes, updated UI using TransferModalPfp, and adjusted onMintFor triggers.
Manifold minting — widget diagnostics
components/manifoldMinting/ManifoldMintingWidget.tsx
Adds mintdebug URL param handling, builds JSON diagnostics, copy-to-clipboard with copy status, guards selection logic, and renders a diagnostics panel when debug enabled.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Connect as SeizeConnectContext
    participant Mint as ManifoldMintingConnect
    participant Selector as RecipientSelector
    participant Callback as onMintFor

    User->>Connect: (optionally) enable DEV impersonation / connect wallet
    Connect-->>Mint: provide `address`, `isConnected`, `isAuthenticated`
    User->>Mint: Toggle "Mint for Fren" / "Mint for Me"
    alt Mint for Fren
        Mint->>Selector: render Fren profile & wallets
        User->>Selector: select Fren profile / wallet
        Selector-->>Mint: update Fren wallet state
        Mint->>Callback: invoke onMintFor(Fren wallet)
    else Mint for Me
        Mint->>Mint: reset Fren state, derive connected recipient
        Mint->>Selector: render connected profile (profile-change disabled)
        User->>Selector: select connected wallet (if multiple)
        Selector-->>Mint: update selected connected wallet
        Mint->>Callback: invoke onMintFor(connected wallet)
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

  • Minting freeze fix #1519: Modifies minting logic/UI in components/manifoldMinting/ManifoldMintingWidget.tsx, overlapping diagnostics and mint flow areas.
  • Transfer NFTs #1528: Integrates TransferModalPfp and recipient selection changes referenced by updated minting components.

Suggested Reviewers

  • simo6529
  • ragnep

Poem

🐰 I hop between dev and main,
Two minting paths within my lane.
Fren or Me, a tiny hop,
Wallets chosen — never stop.
Carrots, code, and a joyful pop! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Mint for me - profile wallet selection' accurately reflects the main changes: introduction of a dual minting flow (Mint For Me vs Mint For Fren) with profile and wallet selection capabilities across multiple components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mint-for-me-profile-wallet-selection

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
components/auth/SeizeConnectContext.tsx (1)

368-376: Nit: consider memoizing the environment/hostname checks.

nodeEnv, isDevLikeEnv, and isLocalHost are recomputed every render but their values never change during the component's lifetime. Wrapping them in useMemo(() => ..., []) (or extracting them to module-level constants) would make the intent clearer and avoid repeated globalThis.window.location.hostname accesses.

♻️ Example: extract to module scope
+// Module-level constants (evaluated once)
+const IS_DEV_LIKE_ENV = (() => {
+  const env = getNodeEnv();
+  return env === "development" || env === "test" || env === "local";
+})();
+
+const IS_LOCAL_HOST =
+  typeof globalThis.window !== "undefined" &&
+  (globalThis.window.location.hostname === "localhost" ||
+    globalThis.window.location.hostname === "127.0.0.1" ||
+    globalThis.window.location.hostname === "::1" ||
+    globalThis.window.location.hostname.endsWith(".local"));
+
 export const SeizeConnectProvider: React.FC<{ children: React.ReactNode }> = ({
   children,
 }) => {
   // ...
-  const nodeEnv = getNodeEnv();
-  const isDevLikeEnv =
-    nodeEnv === "development" || nodeEnv === "test" || nodeEnv === "local";
-  const isLocalHost =
-    globalThis.window !== undefined &&
-    (globalThis.window.location.hostname === "localhost" ||
-      globalThis.window.location.hostname === "127.0.0.1" ||
-      globalThis.window.location.hostname === "::1" ||
-      globalThis.window.location.hostname.endsWith(".local"));
   const impersonatedAddress =
-    isDevLikeEnv &&
-    isLocalHost &&
+    IS_DEV_LIKE_ENV &&
+    IS_LOCAL_HOST &&
     publicEnv.USE_DEV_AUTH === "true" &&
components/manifoldMinting/ManifoldMintingWidget.tsx (2)

207-244: buildMintDiagnostics is also called during render — consider memoizing or deferring.

printMintDebug (line 558) calls buildMintDiagnostics() synchronously in the render path, which in turn calls getSelectedMerkleProofs(), getValue(), and conditionally getMintArgs(). Since this is gated behind isMintDebugEnabled, the impact is negligible in production — but when the flag is on, it re-runs every render cycle.

Not a blocker; just flagging for awareness.


246-256: setTimeout in finally isn't cleared on unmount.

If the component unmounts within the 2-second window, setCopyStatus("") will fire on an unmounted component. React 18+ no longer warns about this, but the stale call is still wasted work. Since this is debug-only tooling, it's low priority.

♻️ Optional cleanup with useRef

If you ever want to tighten this up:

+ const copyTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
+ useEffect(() => () => clearTimeout(copyTimeoutRef.current), []);
  
  const onCopyMintDiagnostics = async () => {
    try {
      const diagnostics = buildMintDiagnostics();
      await navigator.clipboard.writeText(JSON.stringify(diagnostics, null, 2));
      setCopyStatus("copied");
    } catch {
      setCopyStatus("failed");
    } finally {
-     setTimeout(() => setCopyStatus(""), 2000);
+     copyTimeoutRef.current = setTimeout(() => setCopyStatus(""), 2000);
    }
  };

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@components/auth/SeizeConnectContext.tsx`:
- Around line 368-377: The code allows client-side impersonation because PUBLIC
runtime vars (USE_DEV_AUTH, DEV_MODE_WALLET_ADDRESS, DEV_MODE_AUTH_JWT) are
baked into the bundle and only gated by getNodeEnv()/isDevLikeEnv in the
impersonatedAddress logic; to fix, either remove/omit those three keys from the
public runtime env at build-time so they never reach the client, or add an
additional deployment-safe guard (e.g., require publicEnv.DEPLOY_ENV ===
'production' or process.env.DEPLOY_ENV === 'production') in the impersonation
check before using USE_DEV_AUTH/DEV_MODE_WALLET_ADDRESS in the
impersonatedAddress computation to ensure impersonation cannot activate due to
NODE_ENV misconfiguration.

In `@components/manifoldMinting/ManifoldMintingConnect.tsx`:
- Around line 72-86: Destructure onMintFor from props and use it instead of
props.onMintFor inside the useEffect, remove props from the dependency array and
include onMintFor (i.e., useEffect deps: [selectedFrenWallet,
selectedMintForMeWallet, mintForFren, account.address, onMintFor]); also remove
the unsafe "as string" cast and explicitly guard that account.address exists
(e.g., if neither selectedMintForMeWallet nor account.address is defined, bail
out) before calling onMintFor with selectedMintForMeWallet ?? account.address,
keeping references to useEffect, selectedFrenWallet, selectedMintForMeWallet,
mintForFren, account.address, and onMintFor.
🧹 Nitpick comments (2)
components/manifoldMinting/ManifoldMintingConnect.tsx (2)

60-63: resetFren is missing from the useEffect dependency array.

The exhaustive-deps rule would flag this. While functionally correct (the state setters inside resetFren are stable), wrapping resetFren in useCallback and adding it to the deps list would be the idiomatic approach.

Proposed fix
- function resetFren() {
-   setSelectedFrenProfile(null);
-   setSelectedFrenWallet(null);
- }
+ const resetFren = useCallback(() => {
+   setSelectedFrenProfile(null);
+   setSelectedFrenWallet(null);
+ }, []);

  useEffect(() => {
    resetFren();
    setMintForFren(false);
- }, [account.address]);
+ }, [account.address, resetFren]);

104-127: noopProfileSelection is recreated on every render — consider hoisting or memoizing.

noopProfileSelection is defined inside printMintForMe, which is called during render. Since RecipientSelector receives a new function reference each time, this could trigger unnecessary re-renders of that component. A module-level no-op would be simpler.

Proposed fix — hoist the no-op

At the top of the file (or outside the component):

+const noopProfileSelection = (_: CommunityMemberMinimal | null) => undefined;
+
 export default function ManifoldMintingConnect(

Then remove the local declaration inside printMintForMe.

Comment thread components/auth/SeizeConnectContext.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@components/manifoldMinting/ManifoldMintingConnect.tsx`:
- Around line 75-93: When mintForFren is true but selectedFrenWallet is empty
the current useEffect calls onMintFor with the user's address; change the
behavior so the effect does not call onMintFor in that case (or explicitly call
onMintFor(null) if you want to signal "no selection") so the parent can disable
the mint action until a fren is chosen. Update the useEffect logic around the
mintForFren / selectedFrenWallet check in ManifoldMintingConnect (the block
referencing mintForFren, selectedFrenWallet, selectedMintForMeWallet,
account.address, and onMintFor) to return early without invoking onMintFor when
mintForFren is true and selectedFrenWallet is falsy.
🧹 Nitpick comments (2)
components/auth/SeizeConnectContext.tsx (2)

368-384: Consider memoizing the impersonation derivation.

getNodeEnv(), the localhost check, and getAddress() are called on every render. While the cost is trivial, wrapping the block in a useMemo (with an empty dep array, since the inputs are static) would make the intent explicit and prevent unnecessary calls.

♻️ Suggested refactor
-  const nodeEnv = getNodeEnv();
-  const isDevLikeEnv =
-    nodeEnv === "development" || nodeEnv === "test" || nodeEnv === "local";
-  const isLocalHost =
-    typeof window !== "undefined" &&
-    (window.location.hostname === "localhost" ||
-      window.location.hostname === "127.0.0.1" ||
-      window.location.hostname === "::1" ||
-      window.location.hostname.endsWith(".local"));
-  const impersonatedAddress =
-    isDevLikeEnv &&
-    isLocalHost &&
-    publicEnv.USE_DEV_AUTH === "true" &&
-    publicEnv.DEV_MODE_WALLET_ADDRESS &&
-    isAddress(publicEnv.DEV_MODE_WALLET_ADDRESS)
-      ? getAddress(publicEnv.DEV_MODE_WALLET_ADDRESS)
-      : undefined;
+  const impersonatedAddress = useMemo(() => {
+    const nodeEnv = getNodeEnv();
+    const isDevLikeEnv =
+      nodeEnv === "development" || nodeEnv === "test" || nodeEnv === "local";
+    const isLocalHost =
+      typeof window !== "undefined" &&
+      (window.location.hostname === "localhost" ||
+        window.location.hostname === "127.0.0.1" ||
+        window.location.hostname === "::1" ||
+        window.location.hostname.endsWith(".local"));
+    return isDevLikeEnv &&
+      isLocalHost &&
+      publicEnv.USE_DEV_AUTH === "true" &&
+      publicEnv.DEV_MODE_WALLET_ADDRESS &&
+      isAddress(publicEnv.DEV_MODE_WALLET_ADDRESS)
+        ? getAddress(publicEnv.DEV_MODE_WALLET_ADDRESS)
+        : undefined;
+  }, []);

614-631: Wallet metadata is absent during impersonation — may confuse dev-mode consumers.

When impersonatedAddress is active, walletName, walletIcon, and isSafeWallet will all be undefined/false since no real wallet is connected. If any downstream component (e.g., wallet display UI) renders based on isConnected === true but also reads walletName, it may show a blank or broken state in dev mode.

Not a production concern, but worth a brief note or hardcoded fallback (e.g., walletName: impersonatedAddress ? "Dev Wallet" : walletInfo?.name) for a smoother dev experience.

Comment thread components/manifoldMinting/ManifoldMintingConnect.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

@prxt6529 prxt6529 merged commit 104a639 into main Feb 12, 2026
7 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants